package com.koron.common.core.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;

public class DateAndTimeUtils {

    /**
     * 字符串+1方法，该方法将其结尾的整数+1,适用于任何以整数结尾的字符串,不限格式，不限分隔符。
     *
     * @param testStr 要+1的字符串
     * @return +1后的字符串
     * @throws NumberFormatException
     * @author zxcvbnmzb
     */
    public static String addOne(String testStr) {
        String[] strs = testStr.split("[^0-9]");//根据不是数字的字符拆分字符串
        String numStr = strs[strs.length - 1];//取出最后一组数字
        if (numStr != null && numStr.length() > 0) {//如果最后一组没有数字(也就是不以数字结尾)，抛NumberFormatException异常
            int n = numStr.length();//取出字符串的长度
            int num = Integer.parseInt(numStr) + 1;//将该数字加一
            String added = String.valueOf(num);
            n = Math.min(n, added.length());
            //拼接字符串
            return testStr.subSequence(0, testStr.length() - n) + added;
        } else {
            throw new NumberFormatException();
        }
    }

    /**
     * 将Long类型的时间戳转换成String 类型的时间格式，时间格式为：yyyy-MM-dd HH:mm:ss
     */
    public static String convertTimeToString(Long time) {
        Assert.notNull(time, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }

    /**
     * 将字符串转日期成Long类型的时间戳，格式为：yyyy-MM-dd HH:mm:ss
     */
    public static Long convertTimeToLong(String time) {
        Assert.notNull(time, "time is null");
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse("2018-05-29 13:52:50", ftf);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 取上一年第一天
     */
    public static LocalDate firstDayOfBeforOneYear() {
        LocalDate today = LocalDate.now().minusYears(1l);
        return today.with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 取上一年的第N天
     */
    public static LocalDate dayOfBeforOneYear(int n) {
        LocalDate today = LocalDate.now().minusYears(1l);
        return today.withDayOfMonth(n);
    }

    /**
     * 取上一年本月的第一天
     */
    public static LocalDate firstDayOfBeforOneYearAndMonth() {
        LocalDate today = LocalDate.now().minusYears(1l);
        return today.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 取上一年本月的最后天
     */
    public static LocalDate lastDayOfBeforOneYearAndMonth() {
        LocalDate today = LocalDate.now().minusYears(1l);
        return today.with(TemporalAdjusters.lastDayOfMonth());
    }


    /**
     * 取本年第一天
     */
    public static LocalDate firstDayOfThisYear() {
        LocalDate today = LocalDate.now();
        return today.with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 取本年最后一天
     */
    public static LocalDate lastDayOfThisYear() {
        LocalDate today = LocalDate.now();
        return today.with(TemporalAdjusters.lastDayOfYear());
    }

    /**
     * 取本月第一天
     */
    public static LocalDate firstDayOfThisMonth() {
        LocalDate today = LocalDate.now();
        return today.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 取本月第N天
     */
    public static LocalDate dayOfThisMonth(int n) {
        LocalDate today = LocalDate.now();
        return today.withDayOfMonth(n);
    }

    /**
     * 取本月最后一天
     */
    public static LocalDate lastDayOfThisMonth() {
        LocalDate today = LocalDate.now();
        return today.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 获取N天以前的日期
     */
    public static LocalDate getDayofBeforToN(long n) {

        return LocalDate.now().minusDays(n);
    }
    /**
     * 获取N天以前的时间
     */
    public static LocalDateTime getTimeofBeforToN(long n) {
        return LocalDateTime.now().minusDays(n);
    }

    /**
     * 取上一年的 N天以前的日期  (去上一年的昨天)
     */
    public static LocalDate getyesterdayofyesterYear(long n) {
        return LocalDate.now().minusYears(1).minusDays(n);
    }


    /**
     * 取本月第一天的开始时间
     */
    public static LocalDateTime startOfThisMonth() {
        return LocalDateTime.of(firstDayOfThisMonth(), LocalTime.MIN);
    }


    /**
     * 取本月最后一天的结束时间
     */
    public static LocalDateTime endOfThisMonth() {
        return LocalDateTime.of(lastDayOfThisMonth(), LocalTime.MAX);
    }


    /**
     * @param date
     * @param format yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、HH:mm:ss、yyyy-MM-dd HH:mm、yyyy-MM-dd HH:mm:ss.SSS*
     *               这四种情况均可以转换，并且输出结果均为： 2019-09-17 00:00:00
     */
    public static Date strtoDate(String date, String format) {
        if (format == null) {
            format = "yyyy-MM-dd";
        }
        return DateUtil.parse(date, format);
    }

    /**
     * LocalDate 转  Date
     *
     * @param localDate
     * @return
     */
    public static Date ldtoDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
    }

    /**
     * LocalDateTime 转  Date
     *
     * @param localdatetime
     * @return
     */
    public static Date ldttoDate(LocalDateTime localdatetime) {
        return Date.from(localdatetime.atZone(ZoneId.systemDefault()).toInstant());
    }


    // 毫秒转小时
    public static BigDecimal longtimeToHour(int newScale, long time) {
        time = time / 1000 / 60; // 分钟数
        double hour = time / 60.0;
        BigDecimal bigDecimal = new BigDecimal(hour);
        // 保留2位小数,向上取整
        return bigDecimal.setScale(newScale, BigDecimal.ROUND_HALF_UP);
    }

    // 毫秒转天
    public static BigDecimal longtimeToDay(long time) {
        double day = time / 1000 / 60 / 60 / 24; // 天数
        BigDecimal bigDecimal = new BigDecimal(day);
        // 四舍五入保留两位小数
        return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    // 毫秒转分钟
    public static BigDecimal longtimeToMin(long time) {
        double day = time / 1000 / 60; // 分钟数
        BigDecimal bigDecimal = new BigDecimal(day);
        // 四舍五入保留两位小数
        return bigDecimal.setScale(0, BigDecimal.ROUND_UP);
    }

    public static String format(LocalDateTime time) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return dtf2.format(time);
    }

    /**
     * 根据时间 和时间格式 校验是否正确
     * @param length 校验的长度
     * @param sDate 校验的日期
     * @param format 校验的格式
     * @return
     */
    public static boolean isLegalDate(int length, String sDate,String format) {
        int legalLen = length;
        if ((sDate == null) || (sDate.length() != legalLen)) {
            return false;
        }
        DateFormat formatter = new SimpleDateFormat(format);
        try {
            Date date = formatter.parse(sDate);
            return sDate.equals(formatter.format(date));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 时间装转换，异常默认失败
     * @param param
     * @return
     */
    public static String converExcelDate(String param) {
        String formatDate;
        try {
            // 以下是针对 1998-09-01 08:00:00.0
            if (param.length() == 21) {
                DateTime parse = DateUtil.parse(param);
                param = DateUtil.format(parse, "yyyy-MM-dd");
            }
            // 以下针对各种奇怪的日期
            formatDate = converFormatDate(param);
        } catch (Exception e) {
            formatDate = "xxx";
        }
        return formatDate;
    }


    /**
     * 转化使劲按
     * @param excelDate
     * @return
     */
    public static String converFormatDate(String excelDate) throws Exception {
        excelDate = StrUtil.replace(excelDate, "年", "-");
        excelDate = StrUtil.replace(excelDate, "月", "-");
        excelDate = StrUtil.replace(excelDate, "日", "");
        excelDate = StrUtil.replace(excelDate, ".", "-");
        excelDate = StrUtil.replace(excelDate, ",", "-");
        excelDate = StrUtil.replace(excelDate, "。", "-");
        excelDate = StrUtil.replace(excelDate, "`", "-");
        excelDate = StrUtil.replace(excelDate, "·", "-");
        excelDate = StrUtil.replace(excelDate, "·", "-");

        // 有两个 - 且中间的数字位数小于2的
        long count = excelDate.chars().filter(ch -> ch == '-').count();
        if (count == 2) {
            List<String> split = StrUtil.split(excelDate, "-");
            String month = split.get(1);
            if (month.length() < 2) {
                month = "0" + month;
            }
            excelDate = StrUtil.join("-", split.get(0), month, split.get(2));
        }

        long count2 = excelDate.chars().filter(ch -> ch == '-').count();
        if (count2 == 1) {
            List<String> split = StrUtil.split(excelDate, "-");
            String month = split.get(1);
            if (month.length() < 2 && StrUtil.isNotBlank(month)) {
                month = "0" + month;
            }
            excelDate = StrUtil.join("-", split.get(0), month);
            excelDate = StrUtil.trim(excelDate);
        }

        // 2022
        if (excelDate.length() == 4 && NumberUtil.isNumber(excelDate)) {
            excelDate = StrUtil.join("-", excelDate, "01-01");
            excelDate = StrUtil.trim(excelDate);
        }

        // 2222-
        if (excelDate.length() == 5 && StrUtil.endWith(excelDate, "-")) {
            excelDate = StrUtil.join("", excelDate, "01-01");
            excelDate = StrUtil.trim(excelDate);
        }

        // 2022-09-
        if (excelDate.length() == 8 && StrUtil.endWith(excelDate, "-")) {
            excelDate = StrUtil.join("", excelDate, "01");
            excelDate = StrUtil.trim(excelDate);
        }

        // 2002-09
        if (excelDate.length() == 7) {
            excelDate = StrUtil.join("-", excelDate, "01");
            excelDate = StrUtil.trim(excelDate);
        }

        // 2002-9
        if (excelDate.length() == 6) {
            excelDate = StrUtil.join("-", excelDate, "01");
            excelDate = StrUtil.trim(excelDate);
        }

        if (excelDate.length() == 8) {
            DateTime parse = DateUtil.parse(excelDate);
            String format = DateUtil.format(parse, "yyyy-MM-dd");
            excelDate = format;
        }
        return excelDate;
    }



}
